if ( np->user_state == UST_OPEN )
netif_start_queue(dev);
- spin_unlock(&np->tx_lock);
- spin_unlock_irq(&np->rx_lock);
+ spin_unlock(&np->rx_lock);
+ spin_unlock_irq(&np->tx_lock);
}
- static void netif_status_change(netif_fe_interface_status_changed_t *status)
- {
- ctrl_msg_t cmsg;
- netif_fe_interface_connect_t up;
- struct net_device *dev;
- struct net_private *np;
-
- DPRINTK(">\n");
- DPRINTK("> status=%d handle=%d mac=%02x:%02x:%02x:%02x:%02x:%02x\n",
- status->status,
- status->handle,
- status->mac[0], status->mac[1], status->mac[2],
- status->mac[3], status->mac[4], status->mac[5]);
-
- if ( netctrl.interface_n <= 0 )
- {
- printk(KERN_WARNING "Status change: no interfaces\n");
- return;
+ static void vif_show(struct net_private *np){
+ #if DEBUG
+ if(np){
+ IPRINTK(" <vif handle=%u %s(%s) evtchn=%u irq=%u tx=%p rx=%p>\n",
+ np->handle,
+ be_state_name[np->backend_state],
+ user_state_name[np->user_state],
+ np->evtchn,
+ np->irq,
+ np->tx,
+ np->rx);
+ } else {
+ IPRINTK("<vif NULL>\n");
}
+ #endif
+ }
- dev = find_dev_by_handle(status->handle);
- if(!dev){
- printk(KERN_WARNING "Status change: invalid netif handle %u\n",
- status->handle);
- return;
- }
- np = dev->priv;
-
- switch ( status->status )
- {
- case NETIF_INTERFACE_STATUS_DESTROYED:
- printk(KERN_WARNING "Unexpected netif-DESTROYED message in state %d\n",
- np->backend_state);
- break;
+ /* Send a connect message to xend to tell it to bring up the interface.
+ */
+ static void send_interface_connect(struct net_private *np){
+ ctrl_msg_t cmsg = {
+ .type = CMSG_NETIF_FE,
+ .subtype = CMSG_NETIF_FE_INTERFACE_CONNECT,
+ .length = sizeof(netif_fe_interface_connect_t),
+ };
+ netif_fe_interface_connect_t *msg = (void*)cmsg.msg;
+
+ DPRINTK(">\n"); vif_show(np);
+ msg->handle = np->handle;
+ msg->tx_shmem_frame = (virt_to_machine(np->tx) >> PAGE_SHIFT);
+ msg->rx_shmem_frame = (virt_to_machine(np->rx) >> PAGE_SHIFT);
+
+ ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+ DPRINTK("<\n");
+ }
- case NETIF_INTERFACE_STATUS_DISCONNECTED:
- if ( np->backend_state != BEST_CLOSED )
- {
- printk(KERN_WARNING "Unexpected netif-DISCONNECTED message"
- " in state %d\n", np->backend_state);
- printk(KERN_INFO "Attempting to reconnect network interface\n");
-
- /* Begin interface recovery.
- *
- * NB. Whilst we're recovering, we turn the carrier state off. We
- * take measures to ensure that this device isn't used for
- * anything. We also stop the queue for this device. Various
- * different approaches (e.g. continuing to buffer packets) have
- * been tested but don't appear to improve the overall impact on
- * TCP connections.
- *
- * TODO: (MAW) Change the Xend<->Guest protocol so that a recovery
- * is initiated by a special "RESET" message - disconnect could
- * just mean we're not allowed to use this interface any more.
- */
-
- /* Stop old i/f to prevent errors whilst we rebuild the state. */
- spin_lock_irq(&np->tx_lock);
- spin_lock(&np->rx_lock);
- netif_stop_queue(dev);
- np->backend_state = BEST_DISCONNECTED;
- spin_unlock(&np->rx_lock);
- spin_unlock_irq(&np->tx_lock);
-
- /* Free resources. */
- free_irq(np->irq, dev);
- unbind_evtchn_from_irq(np->evtchn);
- free_page((unsigned long)np->tx);
- free_page((unsigned long)np->rx);
- }
+ /* Send a driver status notification to the domain controller. */
+ static int send_driver_status(int ok)
+ {
+ int err = 0;
+ ctrl_msg_t cmsg = {
+ .type = CMSG_NETIF_FE,
+ .subtype = CMSG_NETIF_FE_DRIVER_STATUS,
+ .length = sizeof(netif_fe_driver_status_t),
+ };
+ netif_fe_driver_status_t *msg = (void*)cmsg.msg;
+
+ msg->status = (ok ? NETIF_DRIVER_STATUS_UP : NETIF_DRIVER_STATUS_DOWN);
+ err = ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+ return err;
+ }
- /* Move from CLOSED to DISCONNECTED state. */
- np->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL);
- np->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL);
- memset(np->tx, 0, PAGE_SIZE);
- memset(np->rx, 0, PAGE_SIZE);
- np->backend_state = BEST_DISCONNECTED;
-
- /* Construct an interface-CONNECT message for the domain controller. */
- cmsg.type = CMSG_NETIF_FE;
- cmsg.subtype = CMSG_NETIF_FE_INTERFACE_CONNECT;
- cmsg.length = sizeof(netif_fe_interface_connect_t);
- up.handle = status->handle;
- up.tx_shmem_frame = virt_to_machine(np->tx) >> PAGE_SHIFT;
- up.rx_shmem_frame = virt_to_machine(np->rx) >> PAGE_SHIFT;
- memcpy(cmsg.msg, &up, sizeof(up));
-
- /* Tell the controller to bring up the interface. */
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
- break;
+ /* Stop network device and free tx/rx queues and irq.
+ */
+ static void vif_release(struct net_private *np){
- case NETIF_INTERFACE_STATUS_CONNECTED:
- if ( np->backend_state == BEST_CLOSED )
- {
- printk(KERN_WARNING "Unexpected netif-CONNECTED message"
- " in state %d\n", np->backend_state);
- break;
- }
+ /* Stop old i/f to prevent errors whilst we rebuild the state. */
+ spin_lock_irq(&np->tx_lock);
+ spin_lock(&np->rx_lock);
+ netif_stop_queue(np->dev);
+ //np->backend_state = BEST_DISCONNECTED;
+ spin_unlock(&np->rx_lock);
+ spin_unlock_irq(&np->tx_lock);
+
+ /* Free resources. */
+ if(np->tx != NULL){
+ free_irq(np->irq, np->dev);
+ unbind_evtchn_from_irq(np->evtchn);
+ free_page((unsigned long)np->tx);
+ free_page((unsigned long)np->rx);
+ np->irq = 0;
+ np->evtchn = 0;
+ np->tx = NULL;
+ np->rx = NULL;
+ }
- memcpy(dev->dev_addr, status->mac, ETH_ALEN);
+ }
- network_connect(dev, status);
+ /* Release vif resources and close it down completely.
+ */
+ static void vif_close(struct net_private *np){
+ DPRINTK(">\n"); vif_show(np);
+ WPRINTK(" Unexpected netif-CLOSED message in state %s\n",
+ be_state_name[np->backend_state]);
+ vif_release(np);
+ np->backend_state = BEST_CLOSED;
+ //todo: take dev down and free.
+ vif_show(np); DPRINTK("<\n");
+ }
- np->evtchn = status->evtchn;
- np->irq = bind_evtchn_to_irq(np->evtchn);
- (void)request_irq(np->irq, netif_int, SA_SAMPLE_RANDOM,
- dev->name, dev);
- netctrl_connected_count();
- vif_wake(dev);
- break;
+ /* Move the vif into disconnected state.
+ * Allocates tx/rx pages.
+ * Sends connect message to xend.
+ */
+ static void vif_disconnect(struct net_private *np){
+ DPRINTK(">\n");
+ if(np->tx) free_page((unsigned long)np->tx);
+ if(np->rx) free_page((unsigned long)np->rx);
+ // Before this np->tx and np->rx had better be null.
+ np->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL);
+ np->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL);
+ memset(np->tx, 0, PAGE_SIZE);
+ memset(np->rx, 0, PAGE_SIZE);
+ np->backend_state = BEST_DISCONNECTED;
+ send_interface_connect(np);
+ vif_show(np); DPRINTK("<\n");
+ }
- case NETIF_INTERFACE_STATUS_CHANGED:
- /* The domain controller is notifying us that a device has been
- * added or removed.
- */
- break;
+ /* Begin interface recovery.
+ *
+ * NB. Whilst we're recovering, we turn the carrier state off. We
+ * take measures to ensure that this device isn't used for
+ * anything. We also stop the queue for this device. Various
+ * different approaches (e.g. continuing to buffer packets) have
+ * been tested but don't appear to improve the overall impact on
+ * TCP connections.
+ *
+ * TODO: (MAW) Change the Xend<->Guest protocol so that a recovery
+ * is initiated by a special "RESET" message - disconnect could
+ * just mean we're not allowed to use this interface any more.
+ */
+ static void vif_reset(struct net_private *np){
+ DPRINTK(">\n");
+ IPRINTK(" Attempting to reconnect network interface: handle=%u\n",
+ np->handle);
+
+ vif_release(np);
+ vif_disconnect(np);
+ vif_show(np); DPRINTK("<\n");
+ }
- default:
- printk(KERN_WARNING "Status change to unknown value %d\n",
- status->status);
- break;
- }
+ /* Move the vif into connected state.
+ * Sets the mac and event channel from the message.
+ * Binds the irq to the event channel.
+ */
+ static void vif_connect(struct net_private *np, netif_fe_interface_status_t *status){
+ struct net_device *dev = np->dev;
+ DPRINTK(">\n");
+ memcpy(dev->dev_addr, status->mac, ETH_ALEN);
+ network_connect(dev, status);
+ np->evtchn = status->evtchn;
+ np->irq = bind_evtchn_to_irq(np->evtchn);
+ (void)request_irq(np->irq, netif_int, SA_SAMPLE_RANDOM, dev->name, dev);
+ netctrl_connected_count();
+ vif_wake(dev);
+ vif_show(np); DPRINTK("<\n");
}
+
/** Create a network device.
* @param handle device handle
* @param val return parameter for created device